<!DOCTYPE html><html class="theme-next gemini use-motion" lang="zh-Hans"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta name="theme-color" content="#222"><script src="/MyBlog/lib/pace/pace.min.js?v=1.0.2"></script><link href="/MyBlog/lib/pace/pace-theme-loading-bar.min.css?v=1.0.2" rel="stylesheet"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><link href="/MyBlog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/MyBlog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/MyBlog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css"><link rel="apple-touch-icon" sizes="180x180" href="/MyBlog/images/apple-touch-icon-next.png?v=5.1.4"><link rel="icon" type="image/png" sizes="32x32" href="/MyBlog/images/bitbug_favicon.ico?v=5.1.4"><link rel="icon" type="image/png" sizes="16x16" href="/MyBlog/images/bitbug_favicon16.ico?v=5.1.4"><link rel="mask-icon" href="/MyBlog/images/logo.svg?v=5.1.4" color="#222"><meta name="keywords" content="前端,"><meta name="description" content="为开发模式与发布模式指定不同的打包入口&amp;emsp;&amp;emsp;默认情况下，Vue项目的开发模式与发布模式，共用同一个打包的入口文件(即src&#x2F;main.js)。为了将项目的开发过程与发布过程分离，我们可以为两种模式，各自指定打包的入口文件。开发模式的入口文件为src&#x2F;main-dev.js发布模式的入口文件为src&#x2F;main-prod.js在vue.config.js导出的配置对象中，我们可以新增"><meta property="og:type" content="article"><meta property="og:title" content="项目优化策略"><meta property="og:url" content="https://gitee.com/yang_yu_xiang/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/index.html"><meta property="og:site_name" content="Yang&#39;s Blog"><meta property="og:description" content="为开发模式与发布模式指定不同的打包入口&amp;emsp;&amp;emsp;默认情况下，Vue项目的开发模式与发布模式，共用同一个打包的入口文件(即src&#x2F;main.js)。为了将项目的开发过程与发布过程分离，我们可以为两种模式，各自指定打包的入口文件。开发模式的入口文件为src&#x2F;main-dev.js发布模式的入口文件为src&#x2F;main-prod.js在vue.config.js导出的配置对象中，我们可以新增"><meta property="og:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/mainprodjs.png"><meta property="article:published_time" content="2020-10-08T01:24:25.000Z"><meta property="article:modified_time" content="2020-10-27T09:01:45.882Z"><meta property="article:author" content="杨雨翔"><meta property="article:tag" content="前端"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/mainprodjs.png"><script type="text/javascript" id="hexo.configurations">var NexT=window.NexT||{},CONFIG={root:"/MyBlog/",scheme:"Gemini",version:"5.1.4",sidebar:{position:"left",display:"post",offset:12,b2t:!1,scrollpercent:!0,onmobile:!0},fancybox:!0,tabs:!0,motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}},duoshuo:{userId:"0",author:"博主"},algolia:{applicationID:"",apiKey:"",indexName:"",hits:{per_page:10},labels:{input_placeholder:"Search for Posts",hits_empty:"We didn't find any results for the search: ${query}",hits_stats:"${hits} results found in ${time} ms"}}}</script><link rel="canonical" href="https://gitee.com/yang_yu_xiang/MyBlog/2020/10/08/项目优化策略/"><title>项目优化策略 | Yang's Blog</title><meta name="generator" content="Hexo 4.2.1"></head><body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans"><div class="container sidebar-position-left page-post-detail"><div class="headband"></div><a href="https://gitee.com/yang_yu_xiang" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513;color:#fff;position:absolute;top:0;border:0;right:0" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style><header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-wrapper"><div class="site-meta"><div class="custom-logo-site-title"><a href="/MyBlog/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Yang's Blog</span> <span class="logo-line-after"><i></i></span></a></div><p class="site-subtitle">永远年轻 永远热泪盈眶</p></div><div class="site-nav-toggle"><button><span class="btn-bar"></span> <span class="btn-bar"></span> <span class="btn-bar"></span></button></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/MyBlog/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i><br>首页</a></li><li class="menu-item menu-item-tags"><a href="/MyBlog/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br>标签</a></li><li class="menu-item menu-item-categories"><a href="/MyBlog/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br>分类</a></li><li class="menu-item menu-item-archives"><a href="/MyBlog/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br>归档</a></li><li class="menu-item menu-item-search"><a href="javascript:;" class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br>搜索</a></li></ul><div class="site-search"><div class="popup search-popup local-search-popup"><div class="local-search-header clearfix"><span class="search-icon"><i class="fa fa-search"></i> </span><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span><div class="local-search-input-wrapper"><input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input"></div></div><div id="local-search-result"></div></div></div></nav></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><div class="post-block"><link itemprop="mainEntityOfPage" href="https://gitee.com/yang_yu_xiang/MyBlog/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="杨雨翔"><meta itemprop="description" content=""><meta itemprop="image" content="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/psb.jpg"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Yang's Blog"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">项目优化策略</h1><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建于" itemprop="dateCreated datePublished" datetime="2020-10-08T09:24:25+08:00">2020-10-08 </time><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-calendar-check-o"></i> </span><span class="post-meta-item-text">更新于&#58;</span> <time title="更新于" itemprop="dateModified" datetime="2020-10-27T17:01:45+08:00">2020-10-27 </time></span><span class="post-comments-count"><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-comment-o"></i> </span><a href="/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/#comments" itemprop="discussionUrl"><span class="post-comments-count valine-comment-count" data-xid="/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/" itemprop="commentCount"></span> </a></span><span class="post-meta-divider">|</span> <span class="page-pv">本文总阅读数 <i class="fa fa-file-o"></i> <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>次</span><div class="post-wordcount"><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i> </span><span class="post-meta-item-text">字数统计&#58;</span> <span title="字数统计">3.1k </span><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-clock-o"></i> </span><span class="post-meta-item-text">阅读时长 &asymp;</span> <span title="阅读时长">12</span></div></div></header><div class="post-body" itemprop="articleBody"><h1 id="为开发模式与发布模式指定不同的打包入口"><a href="#为开发模式与发布模式指定不同的打包入口" class="headerlink" title="为开发模式与发布模式指定不同的打包入口"></a>为开发模式与发布模式指定不同的打包入口</h1><p>&emsp;&emsp;默认情况下，Vue项目的开发模式与发布模式，共用同一个打包的入口文件(<strong>即src/main.js</strong>)。为了将项目的开发过程与发布过程分离，我们可以为两种模式，各自指定打包的入口文件。</p><ul><li>开发模式的入口文件为src/main-dev.js</li><li>发布模式的入口文件为src/main-prod.js</li></ul><p>在<code>vue.config.js</code>导出的配置对象中，我们可以新增<code>configureWebpack</code>或<code>chainWebpack</code>节点，来自定义webpack的打包配置</p><p>在这里,configureWebpack和chainWebpack的作用相同，唯一的区别就是它们修改webpack配置的方式不同:</p><ul><li>chainWebpack通过<code>链式编程</code>的形式，来修改默认的webpack配置</li><li>configureWebpack通过<code>操作对象</code>的形式，来修改默认的webpack配置</li></ul><p>我们先删除main.js,把内容复制到<code>main-dev.js</code>和<code>main-prod.js</code>中<br><img src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/mainprodjs.png" alt=""></p><p>下面通过chainWebpack自定义打包入口</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//module.exports暴露配置对象</span></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    <span class="comment">//chainwebpack声明了一个配置节点，config接收默认webpack配置对象</span></span><br><span class="line">    chainwebpack: <span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">//判断产品处于什么模式</span></span><br><span class="line">        config.when(process.env.NODE_ENV=== <span class="string">'production'</span>,config=&gt;&#123;</span><br><span class="line">            <span class="comment">//.entry得到默认的打包入口，clear清空默认的打包入口，add新增自己的打包入口</span></span><br><span class="line">            config.entry(<span class="string">'app'</span>).clear().add(<span class="string">'./src/main-prod.js'</span>)</span><br><span class="line">        &#125;)</span><br><span class="line">        config.when(process.env.NODE_ENV === <span class="string">'development'</span>,config=&gt;&#123;</span><br><span class="line">            config.entry(<span class="string">'app'</span>).clear().add(<span class="string">'./src/main-dev.js'</span>)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样，在发布阶段的修改就可以在<code>main-prod.js</code>中进行</p><a id="more"></a><h1 id="通过externals加载外部CDN资源"><a href="#通过externals加载外部CDN资源" class="headerlink" title="通过externals加载外部CDN资源"></a>通过externals加载外部CDN资源</h1><p>&emsp;&emsp;默认情况下，通过import语法导入的第三方依赖包，最终会被<strong>打包合并到同一个文件</strong>中，从而导致打包成功后，单文件体积过大的问题。<br>&emsp;&emsp;为了解决上述问题，可以通过webpack的<code>externals</code>节点，来配置并加载外部的CDN资源。凡是声明在externals中的第三方依赖包，都不会被打包。</p><p>具体配置代码如下:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在vue.config.js的发布模式中</span></span><br><span class="line">config.when(process.env.NODE_ENV=== <span class="string">'production'</span>,config=&gt;&#123;</span><br><span class="line">    <span class="comment">//修改打包入口</span></span><br><span class="line">    config.entry(<span class="string">'app'</span>).clear().add(<span class="string">'./src/main-projs'</span>)</span><br><span class="line">    <span class="comment">//主要代码</span></span><br><span class="line">    config.set(<span class="string">'externals'</span>,&#123;</span><br><span class="line">        <span class="comment">//忽略库名  npm包名</span></span><br><span class="line">        vue:<span class="string">'vue'</span>,</span><br><span class="line">        <span class="string">'vue-router'</span>:<span class="string">'VueRouter'</span>,</span><br><span class="line">        axios: <span class="string">'axios'</span>,</span><br><span class="line">        echarts: <span class="string">'echarts'</span> ,</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>同时，需要在<code>public/index.html</code>文件的头部，添加如下的CDN资源引用:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://cdn.staticfile.org/vue/2.5.22/vue.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://edn.staticfile.org/vue-router/3.0.1/ve-router.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://cdn.staticfile.org/axios/0.18.0/axios.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 注意：如果有css资源也需要并且可以CDN引入的，也需要引入 --&gt;</span></span><br></pre></td></tr></table></figure><h1 id="通过CDN优化Element-UI的打包"><a href="#通过CDN优化Element-UI的打包" class="headerlink" title="通过CDN优化Element UI的打包"></a>通过CDN优化Element UI的打包</h1><p>&emsp;&emsp;ElementUI打包完体积也很大，但是配置稍微有点不一样，单独开一个大标题讲.由于体积问题，elementui是按需加载的，但是用了CDN我们就不需要按需加载，能很快的把elementui的所有资源都拿过来，所以操作流程如下：</p><ul><li>在main-prod.js中，注释掉element-ui按需加载的代码</li><li>在index.html的头部区域中，通过CDN加载element-ui的js和css样式</li></ul><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- element-ui 的样式表文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">href</span>=<span class="string">"https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css"</span> /&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- element-ui的js 文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://cdn.staticfile.org/element-ui/2.8.2/index.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这样，我们就可以把按需加载elementui的地方注释或删除掉了</p><h1 id="路由懒加载"><a href="#路由懒加载" class="headerlink" title="路由懒加载"></a>路由懒加载</h1><p>&emsp;&emsp;当打包构建项目时，JavaScript包会变得非常大，影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块，然后当路由被访问的时候才加载对应组件，这样就更加高效了。</p><p>具体需要3步:</p><ul><li>安装<code>@babel/plugin-syntax-dynamic-import</code>包。</li><li>在<code>babel.config.js</code>配置文件中声明该插件。</li><li>将路由改为按需加载的形式，示例代码如下</li></ul><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// import中的内容为路由分组/路由组件存放路径</span></span><br><span class="line"><span class="keyword">const</span> Foo = <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: "group-foo"*/</span> <span class="string">'./Foo.vue'</span> )</span><br><span class="line"><span class="keyword">const</span> Bar = <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">import</span>(<span class="comment">/* webpackchunkName: "group-foo"*/</span> <span class="string">'./Bar.vue'</span> )</span><br><span class="line"><span class="keyword">const</span> Baz = <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: "group-boo"*/</span> <span class="string">'./Baz.vue'</span>)</span><br><span class="line"><span class="comment">//Foo和Bar在同一个分组，打包后会被放到同一个js文件中，请求其中一个路由时，另一个也会顺便被请求回来</span></span><br></pre></td></tr></table></figure><p>然后，我们把普通的import导入方式删除就行了</p><p>具体参考链接：<br><a href="https://router.vuejs.org/zh/guide/advanced/lazy-loading.html" target="_blank" rel="noopener">https://router.vuejs.org/zh/guide/advanced/lazy-loading.html</a></p><h1 id="通过优化css包并将其从js中分离"><a href="#通过优化css包并将其从js中分离" class="headerlink" title="通过优化css包并将其从js中分离"></a>通过优化css包并将其从js中分离</h1><p>详见 <a href="http://yang_yu_xiang.gitee.io/myblog/2020/07/30/Webpack%EF%BC%88%E4%BA%8C%EF%BC%89/" target="_blank" rel="noopener">Webpack（二）</a>中mode的生产模式中的优化策略</p><h1 id="tree-shaking"><a href="#tree-shaking" class="headerlink" title="tree shaking"></a>tree shaking</h1><p>tree shaking的作用：去除无用代码<br>前提：</p><ul><li>必须使用 ES6 模块化</li><li>开启 production 环境 （这样就自动会把无用代码去掉）<br>这样，在打包构建的时候，会自动进行<code>tree shaking</code><br>但是，在一些webpack版本中，可能会摇掉一些css等的代码，因为css我们只是引入但是斌没有使用。这时候我们需要在 package.json 中配置：<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//"sideEffects": false表示所有代码都没有副作用（都可以进行 tree shaking），这样会导致的问题：可能会把 css / @babel/polyfill 文件干掉（副作用）</span></span><br><span class="line"><span class="string">"sideEffects"</span>: [<span class="string">"*.css"</span>, <span class="string">"*.less"</span>]<span class="comment">//不会对css/less文件tree shaking处理</span></span><br></pre></td></tr></table></figure><h1 id="one-Of"><a href="#one-Of" class="headerlink" title="one Of"></a>one Of</h1>&emsp;&emsp;oneOf：匹配到 loader 后就不再向后进行匹配，优化生产环境的打包构建速度,但是存在一个问题，就是如果我们有对两个js文件进行处理的loader，匹配到一个就不会继续匹配，所以我们要提一个出来到one Of外面<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>: &#123;</span><br><span class="line">  rules: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">// js 语法检查</span></span><br><span class="line">      test: <span class="regexp">/\.js$/</span>,</span><br><span class="line">      exclude: <span class="regexp">/node_modules/</span>,</span><br><span class="line">      <span class="comment">// 优先执行</span></span><br><span class="line">      enforce: <span class="string">'pre'</span>,</span><br><span class="line">      loader: <span class="string">'eslint-loader'</span>,</span><br><span class="line">      options: &#123;</span><br><span class="line">        fix: <span class="literal">true</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">// oneOf 优化生产环境的打包构建速度</span></span><br><span class="line">      <span class="comment">// 以下loader只会匹配一个（匹配到了后就不会再往下匹配了）</span></span><br><span class="line">      <span class="comment">// 注意：不能有两个配置处理同一种类型文件（所以把eslint-loader提取出去放外面）</span></span><br><span class="line">      oneOf: [</span><br><span class="line">        &#123;</span><br><span class="line">          test: <span class="regexp">/\.css$/</span>,</span><br><span class="line">          use: [...commonCssLoader]</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          test: <span class="regexp">/\.less$/</span>,</span><br><span class="line">          use: [...commonCssLoader, <span class="string">'less-loader'</span>]</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="comment">// js 兼容性处理</span></span><br><span class="line">          test: <span class="regexp">/\.js$/</span>,</span><br><span class="line">          exclude: <span class="regexp">/node_modules/</span>,</span><br><span class="line">          loader: <span class="string">'babel-loader'</span>,</span><br><span class="line">          options: &#123;</span><br><span class="line">            presets: [</span><br><span class="line">              [</span><br><span class="line">                <span class="string">'@babel/preset-env'</span>,</span><br><span class="line">                &#123;</span><br><span class="line">                  useBuiltIns: <span class="string">'usage'</span>,</span><br><span class="line">                  corejs: &#123;<span class="attr">version</span>: <span class="number">3</span>&#125;,</span><br><span class="line">                  targets: &#123;</span><br><span class="line">                    chrome: <span class="string">'60'</span>,</span><br><span class="line">                    firefox: <span class="string">'50'</span></span><br><span class="line">                  &#125;</span><br><span class="line">                &#125;</span><br><span class="line">              ]</span><br><span class="line">            ]</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          test: <span class="regexp">/\.(jpg|png|gif)/</span>,</span><br><span class="line">          loader: <span class="string">'url-loader'</span>,</span><br><span class="line">          options: &#123;</span><br><span class="line">            limit: <span class="number">8</span> * <span class="number">1024</span>,</span><br><span class="line">            name: <span class="string">'[hash:10].[ext]'</span>,</span><br><span class="line">            outputPath: <span class="string">'imgs'</span>,</span><br><span class="line">            esModule: <span class="literal">false</span></span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          test: <span class="regexp">/\.html$/</span>,</span><br><span class="line">          loader: <span class="string">'html-loader'</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          exclude: <span class="regexp">/\.(js|css|less|html|jpg|png|gif)/</span>,</span><br><span class="line">          loader: <span class="string">'file-loader'</span>,</span><br><span class="line">          options: &#123;</span><br><span class="line">            outputPath: <span class="string">'media'</span></span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure></li></ul><h1 id="code-split-代码分割"><a href="#code-split-代码分割" class="headerlink" title="code split 代码分割"></a>code split 代码分割</h1><p>&emsp;&emsp;代码分割主要有两种场景：单入口场景和多入口场景。<br>&emsp;&emsp;将打包输出的一个大的 bundle.js 文件拆分成多个小文件，这样可以并行加载多个文件，比加载一个文件更快。<br>&emsp;&emsp;比如我们在开发单页面应用的时候，如vue，整个页面是一个非常庞大的文件，那么我们肯定要按照路由去拆分不同的文件，从而实现按需加载，这时候拆分文件就需要使用代码分割了</p><h2 id="多入口拆分"><a href="#多入口拆分" class="headerlink" title="多入口拆分"></a>多入口拆分</h2><p>多入口：有几个入口，最终输出就有几个bundle<br>问题：很难去维护多入口，如果要修改多个页面总得去修改多入口</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">entry: &#123;</span><br><span class="line">    <span class="comment">// 多入口：有几个入口，最终输出就有几个bundle</span></span><br><span class="line">    index: <span class="string">'./src/js/index.js'</span>,</span><br><span class="line">    test: <span class="string">'./src/js/test.js'</span></span><br><span class="line">  &#125;,</span><br><span class="line">  output: &#123;</span><br><span class="line">    <span class="comment">// [name]：取文件名</span></span><br><span class="line">    filename: <span class="string">'js/[name].[contenthash:10].js'</span>,</span><br><span class="line">    path: resolve(__dirname, <span class="string">'build'</span>)</span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure><h2 id="optimization"><a href="#optimization" class="headerlink" title="optimization"></a>optimization</h2><p>optimization： 将 <code>node_modules</code>中的代码单独打包</p><ul><li>将 <code>node_modules</code>中的代码单独打包（大小超过30kb）</li><li>自动分析多入口<code>chunk</code>中，有没有公共的文件。如果有会打包成单独一个chunk(比如两个模块中都引入了<code>jquery</code>，正常情况下多入口页面会打包两个引入<code>jquery</code>的文件，使用<code>optimization</code>会被打包成一个单独的文件，不会重复打包多次)（大小超过30kb）<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">optimization: &#123;</span><br><span class="line">    splitChunks: &#123;</span><br><span class="line">      chunks: <span class="string">'all'</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure></li></ul><h2 id="import-动态导入语法："><a href="#import-动态导入语法：" class="headerlink" title="import 动态导入语法："></a>import 动态导入语法：</h2><ul><li>通过js代码，让某个文件被单独打包成一个<code>chunk</code>，采用id命名（0、1、2、3…），避免命名冲突</li><li><code>import</code>动态导入语法：能将某个文件单独打包(<code>test</code>文件不会和<code>index</code>打包在同一个文件而是单独打包)</li><li><code>webpackChunkName</code>:指定test单独打包后文件的名字</li><li>一般在单入口文件中和<code>optimization</code>配合使用<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span>(<span class="comment">/* webpackChunkName: 'test' */</span><span class="string">'./test'</span>)</span><br><span class="line">  .then(<span class="function">(<span class="params">&#123; mul, count &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 文件加载成功~</span></span><br><span class="line">    <span class="comment">// eslint-disable-next-line</span></span><br><span class="line">    <span class="built_in">console</span>.log(mul(<span class="number">2</span>, <span class="number">5</span>));</span><br><span class="line">  &#125;)</span><br><span class="line">  .catch(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// eslint-disable-next-line</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'文件加载失败~'</span>);</span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure></li></ul><h1 id="lazy-loading（懒加载-预加载）"><a href="#lazy-loading（懒加载-预加载）" class="headerlink" title="lazy loading（懒加载/预加载）"></a>lazy loading（懒加载/预加载）</h1><p>1、懒加载：当文件需要使用时才加载（需要代码分割）。但是如果资源较大，加载时间就会较长，有延迟。<br>2、正常加载：可以认为是并行加载（同一时间加载多个文件）没有先后顺序，先加载了不需要的资源就会浪费时间。<br>3、预加载 prefetch（兼容性很差）：会在使用之前，提前加载。等其他资源加载完毕，浏览器空闲了，再偷偷加载这个资源。这样在使用时已经加载好了，速度很快。所以在懒加载的基础上加上预加载会更好。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">document</span>.getElementById(<span class="string">'btn'</span>).onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 将import的内容放在异步回调函数中使用，点击按钮，test.js才会被加载(不会重复加载)</span></span><br><span class="line">  <span class="comment">// webpackChunkName:打包完的文件</span></span><br><span class="line">  <span class="comment">// webpackPrefetch: true表示开启预加载</span></span><br><span class="line">  <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: 'test', webpackPrefetch: true */</span><span class="string">'./test'</span>).then(<span class="function">(<span class="params">&#123; mul &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(mul(<span class="number">4</span>, <span class="number">5</span>));</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">import</span>(<span class="string">'./test'</span>).then(<span class="function">(<span class="params">&#123; mul &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(mul(<span class="number">2</span>, <span class="number">5</span>))</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h1 id="多进程打包"><a href="#多进程打包" class="headerlink" title="多进程打包"></a>多进程打包</h1><p>&emsp;&emsp;在js中，主线程是<strong>单线程</strong>的，同一时间只能干一件事，如果事情比较多就要等很久很久才能干下一件事，所以我们可以使用<strong>多线程</strong>的方式来优化打包速度。</p><blockquote><p>npm install thread-loader -D</p></blockquote><p>一般我们都把这个包给babel用</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="comment">//在babel loader中</span></span><br><span class="line">  test: <span class="regexp">/\.js$/</span>,</span><br><span class="line">  exclude: <span class="regexp">/node_modules/</span>,</span><br><span class="line">  use: [</span><br><span class="line">    <span class="comment">/* </span></span><br><span class="line"><span class="comment">      thread-loader会对其后面的loader（这里是babel-loader）开启多进程打包。 </span></span><br><span class="line"><span class="comment">      进程启动大概为600ms，进程通信也有开销。(启动的开销比较昂贵，不要滥用)</span></span><br><span class="line"><span class="comment">      只有工作消耗时间比较长，才需要多进程打包</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    &#123;</span><br><span class="line">      loader: <span class="string">'thread-loader'</span>,</span><br><span class="line">      options: &#123;</span><br><span class="line">        workers: <span class="number">2</span> <span class="comment">// 进程2个</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      loader: <span class="string">'babel-loader'</span>,</span><br><span class="line">      options: &#123;</span><br><span class="line">        presets: [</span><br><span class="line">          [</span><br><span class="line">            <span class="string">'@babel/preset-env'</span>,</span><br><span class="line">            &#123;</span><br><span class="line">              useBuiltIns: <span class="string">'usage'</span>,</span><br><span class="line">              corejs: &#123; <span class="attr">version</span>: <span class="number">3</span> &#125;,</span><br><span class="line">              targets: &#123;</span><br><span class="line">                chrome: <span class="string">'60'</span>,</span><br><span class="line">                firefox: <span class="string">'50'</span></span><br><span class="line">              &#125;</span><br><span class="line">            &#125;</span><br><span class="line">          ]</span><br><span class="line">        ],</span><br><span class="line">        <span class="comment">// 开启babel缓存</span></span><br><span class="line">        <span class="comment">// 第二次构建时，会读取之前的缓存</span></span><br><span class="line">        cacheDirectory: <span class="literal">true</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure><h1 id="dll"><a href="#dll" class="headerlink" title="dll"></a>dll</h1><p>dll：让某些库单独打包，后直接引入到 build 中。可以在 code split 分割出 node_modules 后再用 dll 更细的分割，优化代码运行的性能。</p><h2 id="为什么需要dll？"><a href="#为什么需要dll？" class="headerlink" title="为什么需要dll？"></a>为什么需要dll？</h2><p>dll 每次重新打包时，第三方库不会重新打包；code split 则会在每次打包时重新打包第三方库，时间上有开销</p><h2 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h2><p>新建<code>webpack.dll.js</code> 配置：(将 jquery 单独打包)</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">  node_modules的库会打包到一起，但是很多库的时候打包输出的js文件就太大了</span></span><br><span class="line"><span class="comment">  使用dll技术，对某些库（第三方库：jquery、react、vue...）进行单独打包</span></span><br><span class="line"><span class="comment">  当运行webpack时，默认查找webpack.config.js配置文件</span></span><br><span class="line"><span class="comment">  需求：需要运行webpack.dll.js文件</span></span><br><span class="line"><span class="comment">    --&gt; webpack --config webpack.dll.js（运行这个指令表示以这个配置文件打包）</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">const</span> &#123; resolve &#125; = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"><span class="keyword">const</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  entry: &#123;</span><br><span class="line">    <span class="comment">//name:库</span></span><br><span class="line">    <span class="comment">// 最终打包生成的[name] --&gt; jquery</span></span><br><span class="line">    <span class="comment">// ['jquery] --&gt; 要打包的库是jquery</span></span><br><span class="line">    jquery: [<span class="string">'jquery'</span>]，</span><br><span class="line">    ...</span><br><span class="line">  &#125;,</span><br><span class="line">  output: &#123;</span><br><span class="line">    <span class="comment">// 输出出口指定</span></span><br><span class="line">    filename: <span class="string">'[name].js'</span>, <span class="comment">// name就是jquery</span></span><br><span class="line">    path: resolve(__dirname, <span class="string">'dll'</span>), <span class="comment">// 打包到dll目录下</span></span><br><span class="line">    library: <span class="string">'[name]_[hash]'</span>, <span class="comment">// 打包的库里面向外暴露出去的内容叫什么名字</span></span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">    <span class="comment">// 打包生成一个manifest.json --&gt; 提供jquery的映射关系（告诉webpack：jquery之后不需要再打包和暴露内容的名称）</span></span><br><span class="line">    <span class="keyword">new</span> webpack.DllPlugin(&#123;</span><br><span class="line">      name: <span class="string">'[name]_[hash]'</span>, <span class="comment">// 映射库的暴露的内容名称</span></span><br><span class="line">      path: resolve(__dirname, <span class="string">'dll/manifest.json'</span>) <span class="comment">// 输出文件路径</span></span><br><span class="line">    &#125;)</span><br><span class="line">  ],</span><br><span class="line">  mode: <span class="string">'production'</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>同时，<code>webpack.config.js</code> 也需要配置：(告诉 webpack 不需要再打包 jquery，并将之前打包好的 jquery 跟其他打包好的资源一同输出到 build 目录下)</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 引入插件</span></span><br><span class="line"><span class="keyword">const</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>);</span><br><span class="line"><span class="keyword">const</span> AddAssetHtmlWebpackPlugin = <span class="built_in">require</span>(<span class="string">'add-asset-html-webpack-plugin'</span>);<span class="comment">//要下载</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// plugins中配置：</span></span><br><span class="line">plugins: [</span><br><span class="line">  <span class="keyword">new</span> HtmlWebpackPlugin(&#123;</span><br><span class="line">    template: <span class="string">'./src/index.html'</span></span><br><span class="line">  &#125;),</span><br><span class="line">  <span class="comment">// 告诉webpack哪些库不参与打包，同时使用时的名称也得变</span></span><br><span class="line">  <span class="keyword">new</span> webpack.DllReferencePlugin(&#123;</span><br><span class="line">    manifest: resolve(__dirname, <span class="string">'dll/manifest.json'</span>)</span><br><span class="line">  &#125;),</span><br><span class="line">  <span class="comment">// 将某个文件打包输出到build目录下，并在html中自动引入该资源</span></span><br><span class="line">  <span class="keyword">new</span> AddAssetHtmlWebpackPlugin(&#123;</span><br><span class="line">    filepath: resolve(__dirname, <span class="string">'dll/jquery.js'</span>)</span><br><span class="line">  &#125;)</span><br><span class="line">],</span><br></pre></td></tr></table></figure></div><div><div class="my_post_copyright"><script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script><script src="https://cdn.bootcss.com/jquery/2.0.0/jquery.min.js"></script><script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script><p><span>本文标题:</span><a href="/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/">项目优化策略</a></p><p><span>文章作者:</span><a href="/" title="访问 杨雨翔 的个人博客">杨雨翔</a></p><p><span>发布时间:</span>2020年10月08日 - 09:24</p><p><span>最后更新:</span>2020年10月27日 - 17:01</p><p><span>原始链接:</span><a href="/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/" title="项目优化策略">https://gitee.com/yang_yu_xiang/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/</a> <span class="copy-path" title="点击复制文章链接"><i class="fa fa-clipboard" data-clipboard-text="https://gitee.com/yang_yu_xiang/MyBlog/2020/10/08/%E9%A1%B9%E7%9B%AE%E4%BC%98%E5%8C%96%E7%AD%96%E7%95%A5/" aria-label="复制成功！"></i></span></p><p><span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p></div><script>var clipboard=new Clipboard(".fa-clipboard");$(".fa-clipboard").click((function(){clipboard.on("success",(function(){swal({title:"",text:"复制成功",icon:"success",showConfirmButton:!0})}))}))</script></div><div style="text-align:center;color:#ccc;font-size:16px">---------------- The End ----------------</div><footer class="post-footer"><div class="post-tags"><a href="/MyBlog/tags/%E5%89%8D%E7%AB%AF/" rel="tag"><i class="fa fa-tag"></i> 前端</a></div><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/MyBlog/2020/10/06/Vue%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E5%8E%9F%E7%90%86/" rel="next" title="Vue双向绑定原理"><i class="fa fa-chevron-left"></i> Vue双向绑定原理</a></div><span class="post-nav-divider"></span><div class="post-nav-prev post-nav-item"><a href="/MyBlog/2020/10/23/TCP%E8%BF%9E%E6%8E%A5%E7%9A%84%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E4%B8%8E%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B/" rel="prev" title="TCP连接的三次握手与四次挥手">TCP连接的三次握手与四次挥手 <i class="fa fa-chevron-right"></i></a></div></div></footer></div></article><div class="post-spread"><div class="jiathis_style"><span class="jiathis_txt">分享到：</span> <a class="jiathis_button_fav">收藏夹</a> <a class="jiathis_button_copy">复制网址</a> <a class="jiathis_button_email">邮件</a> <a class="jiathis_button_weixin">微信</a> <a class="jiathis_button_qzone">QQ空间</a> <a class="jiathis_button_tqq">腾讯微博</a> <a class="jiathis_button_douban">豆瓣</a> <a class="jiathis_button_share">一键分享</a> <a href="http://www.jiathis.com/share?uid=2140465" class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis" target="_blank">更多</a> <a class="jiathis_counter_style"></a></div><script type="text/javascript">var jiathis_config={data_track_clickback:!0,summary:"",shortUrl:!1,hideMore:!1}</script><script type="text/javascript" src="http://v3.jiathis.com/code/jia.js?uid=" charset="utf-8"></script></div></div></div><div class="comments" id="comments"></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span> <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span> <span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div id="sidebar-dimmer"></div><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">文章目录</li><li class="sidebar-nav-overview" data-target="site-overview-wrap">站点概览</li></ul><section class="site-overview-wrap sidebar-panel"><div class="site-overview"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"><img class="site-author-image" itemprop="image" src="https://gitee.com/yang_yu_xiang/BlogImages/raw/master/img/psb.jpg" alt="杨雨翔"><p class="site-author-name" itemprop="name">杨雨翔</p><p class="site-description motion-element" itemprop="description"></p></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"><a href="/MyBlog/archives/"><span class="site-state-item-count">53</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"><a href="/MyBlog/categories/index.html"><span class="site-state-item-count">12</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"><a href="/MyBlog/tags/index.html"><span class="site-state-item-count">32</span> <span class="site-state-item-name">标签</span></a></div></nav><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://gitee.com/yang_yu_xiang" target="_blank" title="码云"><i class="fa fa-fw fa-git"></i>码云</a> </span><span class="links-of-author-item"><a href="http://wpa.qq.com/msgrd?v=3&uin=1372201820&site=qq&menu=yes" target="_blank" title="QQ"><i class="fa fa-fw fa-qq"></i>QQ</a> </span><span class="links-of-author-item"><a href="https://github.com/gezhicui" target="_blank" title="Github"><i class="fa fa-fw fa-github"></i>Github</a> </span><span class="links-of-author-item"><a href="mailto:1372201820@qq.com" target="_blank" title="E-Mail"><i class="fa fa-fw fa-envelope"></i>E-Mail</a></span></div><div class="links-of-blogroll motion-element links-of-blogroll-block"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-link"></i> 友情链接</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"><a href="https://cloudhao.top/#/search/%E5%9F%9F%E5%90%8D" title="陈昀昊的小窝" target="_blank">陈昀昊的小窝</a></li><li class="links-of-blogroll-item"><a href="http://www.shezhiwei.top/" title="佘智伟的博客" target="_blank">佘智伟的博客</a></li><li class="links-of-blogroll-item"><a href="https://blog.csdn.net/qq_43185206" title="阿呆的小鸡仔" target="_blank">阿呆的小鸡仔</a></li></ul></div></div></section><section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active"><div class="post-toc"><div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#为开发模式与发布模式指定不同的打包入口"><span class="nav-number">1.</span> <span class="nav-text">为开发模式与发布模式指定不同的打包入口</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#通过externals加载外部CDN资源"><span class="nav-number">2.</span> <span class="nav-text">通过externals加载外部CDN资源</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#通过CDN优化Element-UI的打包"><span class="nav-number">3.</span> <span class="nav-text">通过CDN优化Element UI的打包</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#路由懒加载"><span class="nav-number">4.</span> <span class="nav-text">路由懒加载</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#通过优化css包并将其从js中分离"><span class="nav-number">5.</span> <span class="nav-text">通过优化css包并将其从js中分离</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#tree-shaking"><span class="nav-number">6.</span> <span class="nav-text">tree shaking</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#one-Of"><span class="nav-number">7.</span> <span class="nav-text">one Of</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#code-split-代码分割"><span class="nav-number">8.</span> <span class="nav-text">code split 代码分割</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#多入口拆分"><span class="nav-number">8.1.</span> <span class="nav-text">多入口拆分</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#optimization"><span class="nav-number">8.2.</span> <span class="nav-text">optimization</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#import-动态导入语法："><span class="nav-number">8.3.</span> <span class="nav-text">import 动态导入语法：</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#lazy-loading（懒加载-预加载）"><span class="nav-number">9.</span> <span class="nav-text">lazy loading（懒加载&#x2F;预加载）</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#多进程打包"><span class="nav-number">10.</span> <span class="nav-text">多进程打包</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#dll"><span class="nav-number">11.</span> <span class="nav-text">dll</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#为什么需要dll？"><span class="nav-number">11.1.</span> <span class="nav-text">为什么需要dll？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#基本使用"><span class="nav-number">11.2.</span> <span class="nav-text">基本使用</span></a></li></ol></li></ol></div></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright">&copy; <span itemprop="copyrightYear">2021</span> <span class="with-love"><i class="fa fa-send"></i> </span><span class="author" itemprop="copyrightHolder">杨雨翔</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="fa fa-area-chart"></i> </span><span class="post-meta-item-text">站点总字数&#58;</span> <span title="站点总字数">61.9k</span></div><div class="busuanzi-count"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="site-uv">本站访问数 <i class="fa fa-user"></i> <span class="busuanzi-value" id="busuanzi_value_site_uv"></span> 人次 </span><span class="site-pv">本站总访问量 <i class="fa fa-eye"></i> <span class="busuanzi-value" id="busuanzi_value_site_pv"></span> 次</span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i> <span id="scrollpercent"><span>0</span>%</span></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/MyBlog/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/MyBlog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/MyBlog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/MyBlog/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/MyBlog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/MyBlog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/MyBlog/js/src/utils.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/motion.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/affix.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/schemes/pisces.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/scrollspy.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/post-details.js?v=5.1.4"></script><script type="text/javascript" src="/MyBlog/js/src/bootstrap.js?v=5.1.4"></script><script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script><script src="//unpkg.com/valine/dist/Valine.min.js"></script><script type="text/javascript">var GUEST=["nick","mail","link"],guest="nick";guest=guest.split(",").filter(e=>GUEST.indexOf(e)>-1),new Valine({el:"#comments",verify:!1,notify:!1,appId:"i5Tl5zN4f4LxoJgipanUuaml-gzGzoHsz",appKey:"wqw6uYNCQkeVxBffKebM29NH",placeholder:"说点什么吧...",avatar:"mm",guest_info:guest,pageSize:"10"})</script><script type="text/javascript">var isfetched=!1,isXml=!0,search_path="search.xml";0===search_path.length?search_path="search.xml":/json$/i.test(search_path)&&(isXml=!1);var path="/MyBlog/"+search_path,onPopupClose=function(t){$(".popup").hide(),$("#local-search-input").val(""),$(".search-result-list").remove(),$("#no-result").remove(),$(".local-search-pop-overlay").remove(),$("body").css("overflow","")};function proceedsearch(){$("body").append('<div class="search-popup-overlay local-search-pop-overlay"></div>').css("overflow","hidden"),$(".search-popup-overlay").click(onPopupClose),$(".popup").toggle();var t=$("#local-search-input");t.attr("autocapitalize","none"),t.attr("autocorrect","off"),t.focus()}var searchFunc=function(t,e,o){"use strict";$("body").append('<div class="search-popup-overlay local-search-pop-overlay"><div id="search-loading-icon"><i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i></div></div>').css("overflow","hidden"),$("#search-loading-icon").css("margin","20% auto 0 auto").css("text-align","center"),$.ajax({url:t,dataType:isXml?"xml":"json",async:!0,success:function(t){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var n=isXml?$("entry",t).map((function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}})).get():t,r=document.getElementById(e),s=document.getElementById(o),a=function(){var t=r.value.trim().toLowerCase(),e=t.split(/[\s\-]+/);e.length>1&&e.push(t);var o=[];if(t.length>0&&n.forEach((function(n){var r=!1,s=0,a=0,i=n.title.trim(),c=i.toLowerCase(),l=n.content.trim().replace(/<[^>]+>/g,""),h=l.toLowerCase(),p=decodeURIComponent(n.url),u=[],f=[];if(""!=i&&(e.forEach((function(t){function e(t,e,o){var n=t.length;if(0===n)return[];var r=0,s=[],a=[];for(o||(e=e.toLowerCase(),t=t.toLowerCase());(s=e.indexOf(t,r))>-1;)a.push({position:s,word:t}),r=s+n;return a}u=u.concat(e(t,c,!1)),f=f.concat(e(t,h,!1))})),(u.length>0||f.length>0)&&(r=!0,s=u.length+f.length)),r){function d(e,o,n,r){for(var s=r[r.length-1],i=s.position,c=s.word,l=[],h=0;i+c.length<=n&&0!=r.length;){c===t&&h++,l.push({position:i,length:c.length});var p=i+c.length;for(r.pop();0!=r.length&&(i=(s=r[r.length-1]).position,c=s.word,p>i);)r.pop()}return a+=h,{hits:l,start:o,end:n,searchTextCount:h}}[u,f].forEach((function(t){t.sort((function(t,e){return e.position!==t.position?e.position-t.position:t.word.length-e.word.length}))}));var g=[];0!=u.length&&g.push(d(0,0,i.length,u));for(var v=[];0!=f.length;){var $=f[f.length-1],C=$.position,m=$.word,x=C-20,w=C+80;x<0&&(x=0),w<C+m.length&&(w=C+m.length),w>l.length&&(w=l.length),v.push(d(0,x,w,f))}v.sort((function(t,e){return t.searchTextCount!==e.searchTextCount?e.searchTextCount-t.searchTextCount:t.hits.length!==e.hits.length?e.hits.length-t.hits.length:t.start-e.start}));var y=parseInt("1");function T(t,e){var o="",n=e.start;return e.hits.forEach((function(e){o+=t.substring(n,e.position);var r=e.position+e.length;o+='<b class="search-keyword">'+t.substring(e.position,r)+"</b>",n=r})),o+=t.substring(n,e.end)}y>=0&&(v=v.slice(0,y));var b="";0!=g.length?b+="<li><a href='"+p+"' class='search-result-title'>"+T(i,g[0])+"</a>":b+="<li><a href='"+p+"' class='search-result-title'>"+i+"</a>",v.forEach((function(t){b+="<a href='"+p+'\'><p class="search-result">'+T(l,t)+"...</p></a>"})),b+="</li>",o.push({item:b,searchTextCount:a,hitCount:s,id:o.length})}})),1===e.length&&""===e[0])s.innerHTML='<div id="no-result"><i class="fa fa-search fa-5x" /></div>';else if(0===o.length)s.innerHTML='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>';else{o.sort((function(t,e){return t.searchTextCount!==e.searchTextCount?e.searchTextCount-t.searchTextCount:t.hitCount!==e.hitCount?e.hitCount-t.hitCount:e.id-t.id}));var a='<ul class="search-result-list">';o.forEach((function(t){a+=t.item})),a+="</ul>",s.innerHTML=a}};r.addEventListener("input",a),$(".local-search-pop-overlay").remove(),$("body").css("overflow",""),proceedsearch()}})};$(".popup-trigger").click((function(t){t.stopPropagation(),!1===isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()})),$(".popup-btn-close").click(onPopupClose),$(".popup").click((function(t){t.stopPropagation()})),$(document).on("keyup",(function(t){27===t.which&&$(".search-popup").is(":visible")&&onPopupClose()}))</script><script src="/MyBlog/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"model":{"jsonPath":"/MyBlog/live2dw/assets/wanko.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"log":false});</script></body></html>